W11_Hash 相關


Posted by Christy on 2021-08-30

密碼  hash 之後,如何驗證

先在註冊頁面,一開始客戶輸入密碼後,就用 PHP 內建函式把密碼 hash,存到資料庫

password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

再到登入頁面,驗證密碼 hash 前後是否一樣

a. 原本的實作是從登入頁面抓取使用者輸入的帳號密碼,然後檢查資料庫裡面有沒有此使用者。

利用 echo $result->num_rows;,會輸出資料庫裡面有幾筆資料,輸出為零代表零筆資料,表示登入帳號或密碼有誤

輸出為一,代表有一筆資料,表示有找到帳號密碼

b. 但因要比對密碼 hash 前後的結果是否一樣,要先把資料庫裡的「hash 過後」的密碼抓出來,接著去拿使用者輸入的密碼,利用 password_verify('rasmuslerdorf', $hash),來比對兩個密碼是否相同。

首先註冊時,先經過內建函式 hash 密碼,再把密碼存進去。所以在資料庫裡面就會變成經過 hash 密碼

登入時,先透過 username 把密碼撈出來,先檢查是否有查到 user,沒有的話就錯誤返回;如果有查到使用者的話,把他的密碼拿出來,之後透 password_verify('rasmuslerdorf', $hash) 做比對,如果兩者相同,通過驗證的話,就登入成功,否則失敗。

改完之後好處,資料庫被偷,駭客不會知道原本是什麼。
就保護了使用者密碼。一般來說會經過 hash 才會存到裡面。


hw1 實作_1.密碼 hash

使用 PHP 內建 hash 函式

// 利用 password_hash()這個函式產生 hash 密碼
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);

註冊跟登入時,驗證客戶端輸入的密碼是否跟資料庫加密後的密碼一致

<?php
  session_start();
  require_once('conn.php');

  if (empty($_POST['username']) || empty($_POST['password'])) {
    header('Location: login.php?errCode=1');
    die();
  }

  $username = $_POST['username'];
  $password = $_POST['password'];
    // 把資料庫的使用者資料先撈出來
  $sql = sprintf("SELECT * FROM christy_w9_users WHERE username = '%s'", $username);
  $result = $conn->query($sql);

  if (!$result) {
    die($conn->error);
  }
    // 先驗證是否有此使用者,如果沒有的話,記得要 exit(),這樣下面的程式碼才不會被執行
  if ($result->num_rows === 0) {
    header('Location: login.php?errCode=2');
    exit();
  }
    // 利用 PHP 內建的 password_verify() 來檢查客戶端輸入的密碼是否跟資料庫裡面 hash 過的密碼一致
  $row = $result->fetch_assoc();
  if (password_verify($password, $row['password'])) {
    $_SESSION['username'] = $username;
    header('Location: index.php');
  } else {
    header('Location: login.php?errCode=2');
  }
?>

code_handle_login.php

<?php
  session_start();
  require_once('conn.php');
  require_once('utils.php');

  if (empty($_POST['username']) || empty($_POST['password'])) {
    header('Location: login.php?errCode=1');
    die();
  }

  $username = $_POST['username'];
  $password = $_POST['password'];

  $sql = "SELECT * FROM users WHERE username = ?";
  $stmt = $conn->prepare($sql);
  $stmt->bind_param('s', $username);
  $result = $stmt->execute();
  if (!$result) {
    die($conn->error);
  }

  $result = $stmt->get_result();
  if ($result->num_rows === 0) {
    header('Location: login.php?errCode=2');
    exit();
  }

  $row = $result->fetch_assoc();
  if (password_verify($password, $row['password'])) {
    $_SESSION['username'] = $username;
    header('Location: index.php');
  } else {
    header('Location: login.php?errCode=2');
  }
?>

code_handle_register.php

<?php 
  require_once('conn.php');

  if (empty($_POST['nickname']) || empty($_POST['username']) || empty($_POST['password'])) {
    header('Location: register.php?errCode=1');
    die();
  }

  $nickname = $_POST['nickname'];
  $username = $_POST['username'];
  $password = password_hash($_POST['password'], PASSWORD_DEFAULT);

  $sql = sprintf("INSERT INTO users(nickname, username, password) VALUES('%s', '%s', '%s')", $nickname, $username, $password);
  $result = $conn->query($sql);

  if (!$result) {
    $code = $conn->errno;
    if ($code === 1062) {
      header('Location: register.php?errCode=2');
    }
    die($conn->error);
  }

  header('Location: index.php');
?>









Related Posts

變數常數命名

變數常數命名

JS Project - Simon Game

JS Project - Simon Game

在 Raspberry Pi 4 使用 TOTOLINK-N150UA-B

在 Raspberry Pi 4 使用 TOTOLINK-N150UA-B


Comments